#include "MyComment.h"

char LoginUserName[128] = {0}; // 保存登录的用户名
int SID;
// SEN *STU = NULL;
void showMenu();
int ret = 0;
// 工作线程，接受服务器返回来的消息
void *work(void *pArg)
{                            // 传入一个套接字
     int sID = *(int *)pArg; // 把套接字从地址里面取出来
     // 用户连接后会创建当前线程，并且会把用户的套接字id通过参数传入进来
     // 这里是把套接字从地址里面取出来
     MSG msg;
     struct sockaddr_in clientAddr;
     socklen_t len = sizeof(clientAddr);
     int ret = 0;
     PVCH *pSC = (PVCH *)msg.buf;
     while (0 < (ret = recv(sID, &msg, sizeof(MSG), 0)))
     {
          // PVCH *pSC = (PVCH *)msg.buf;
          printf("%s:[%s]\n", pSC->selfName, pSC->text);
     }
     if (ret <= 0)
     {
          printf("接受数据出错了\n");
     }
     //  if (strcmp(pSC->text, "quit") == 0)
     //  {
     //       msg.type = message;
     //  }
}
int Enroll(int sID) // 注册
{
     SEN zhuc;
     printf("请输入用户名 密码 性别\n");
     scanf("%s %s %s", zhuc.name, zhuc.pwd, zhuc.sex);
     MSG msg;
     msg.type = StudentEnroll;
     memcpy(msg.buf, &zhuc, sizeof(SEN)); // 把注册结构体拷贝到消息结构体的仓库中
     // 把消息发送给服务器
     int ret = send(sID, &msg, sizeof(msg), 0);
     error("发送注册数据失败\n", ret);
     // 接受服务器的回复
     struct sockaddr_in serverAddr;
     socklen_t len = sizeof(serverAddr);
     ret = recv(sID, &msg, sizeof(msg), 0);
     if (msg.type == ok)
     {
          printf("学生注册成功\n");
          return 1;
     }
     else
     {
          printf("用户名重复,请重新注册\n");
          return -1;
     }
}
int Login(int sID) // 登录
{
     SEN denglu;
     printf("请输入用户名 密码\n");
     scanf("%s %s", denglu.name, denglu.pwd);
     MSG msg;
     msg.type = StudentLogin;
     memcpy(msg.buf, &denglu, sizeof(SEN)); // 把注册结构体拷贝到消息结构体的仓库中
     int ret = send(sID, &msg, sizeof(msg), 0);
     error("发送注册数据失败", ret);
     // 接受服务器的回复
     struct sockaddr_in serverAddr;
     socklen_t len = sizeof(serverAddr);
     ret = recv(sID, &msg, sizeof(msg), 0);
     if (msg.type == ok)
     {
          printf("学生登陆成功\n");
          strcpy(LoginUserName, denglu.name); // 把用户名保存到全局变量中，其他地方都可以使用
          showMenu();
          return 1;
     }
     else
     {
          printf("登录失败,请重新登录\n");
          return -1;
     }
}
void PrivateChat(int sID) // 私聊
{
     MSG msg;
     PVCH sl;
     strcpy(sl.selfName, LoginUserName); // 自己的名字
     msg.type = inprivate;               // 修改自己私聊状态
     memcpy(msg.buf, sl.selfName, sizeof(sl));
     ret = send(sID, &msg, sizeof(msg), 0);
     if (ret <= 0)
     {
          printf("发送数据失败\n");
          return;
     }
     printf("请输入要私聊的对象\n");
     scanf("%s", sl.destName); // 私聊对象名字
     msg.type = Inquire;
     memcpy(msg.buf, &sl, sizeof(sl));
     ret = send(sID, &msg, sizeof(msg), 0);
     if (ret <= 0)
     {
          printf("发送数据失败\n");
          return;
     }
     struct sockaddr_in serverAddr;
     socklen_t len = sizeof(serverAddr);
     ret = recv(sID, &msg, sizeof(msg), 0);
     if (ret <= 0)
     {
          printf("接收数据失败\n");
          return;
     }
     if (msg.type == ok)
     {
          printf("请输入聊天的内容\n");
          pthread_t pt; // 读取服务器返回的消息
          // 启动一个接受消息的线程
          pthread_create(&pt, NULL, work, &sID);
          while (1)
          {
               scanf("%s", sl.text);
               msg.type = privatechat; // 消息类型为单聊
               if (strcmp(sl.text, "sb") == 0)
               {
                    strcpy(sl.text, "**");
               }
               // 把单聊的内容拷贝到消息的仓库中
               memcpy(msg.buf, &sl, sizeof(sl));

               // 把消息发送给服务器
               ret = send(sID, &msg, sizeof(msg), 0);
               if (ret <= 0)
               {
                    printf("发送数据失败\n");
                    return;
               }
               if (strcmp(sl.text, "quit") == 0)
               {
                    pthread_cancel(pt);
                    msg.type = outprivate;
                    ret = send(sID, &msg, sizeof(msg), 0);
                    if (ret <= 0)
                    {
                         printf("发送数据失败\n");
                         return;
                    }
                    return;
               }
          }
     }
     else if (msg.type == no)
     {
          printf("对方离线,请留言\n");
          while (1)
          {
               scanf("%s", sl.text);
               msg.type = message;
               // 把单聊的内容拷贝到消息的仓库中
               memcpy(msg.buf, &sl, sizeof(sl));

               // 把消息发送给服务器
               ret = send(sID, &msg, sizeof(msg), 0);
               if (ret <= 0)
               {
                    printf("发送数据失败\n");
                    return;
               }
               if (strcmp(sl.text, "quit") == 0)
               {
                    msg.type = outprivate;
                    ret = send(sID, &msg, sizeof(msg), 0);
                    if (ret <= 0)
                    {
                         printf("发送数据失败\n");
                         return;
                    }
                    return;
               }
          }
     }
     else if (msg.type == notfind)
     {
          printf("对方不存在\n");
          msg.type = outprivate;
          ret = send(sID, &msg, sizeof(msg), 0);
          if (ret <= 0)
          {
               printf("发送数据失败\n");
               return;
          }
          return;
     }
}
void GroupChat(int sID) // 群聊
{
     pthread_t pt; // 读取服务器返回的消息
     MSG msg;
     PVCH sl;
     strcpy(sl.selfName, LoginUserName); // 自己的名字
     // 启动一个接受消息的线程
     pthread_create(&pt, NULL, work, &sID);
     printf("请输入聊天的内容\n");
     while (1)
     {
          scanf("%s", sl.text);
          msg.type = groupchat; // 消息类型为群聊
          // 把群聊的内容拷贝到消息的仓库中
          memcpy(msg.buf, &sl, sizeof(sl));

          // 把消息发送给服务器
          int ret = send(sID, &msg, sizeof(msg), 0);
          if (ret <= 0)
          {
               printf("发送数据失败\n");
               return;
          }
          if (strcmp(sl.text, "quit") == 0)
          {
               pthread_cancel(pt);
               break;
          }
     }
}
void Grade(int sID) // 打评分
{
     MSG msg;
     msg.type = findteacher;
     ret = send(sID, &msg, sizeof(msg), 0);
     if (ret <= 0)
     {
          printf("发送数据失败\n");
          return;
     }
     struct sockaddr_in serverAddr;
     socklen_t len = sizeof(serverAddr);
     while (0 < (ret = recv(sID, &msg, sizeof(msg), 0)))
     {
          if (msg.type == viewover) // 查询结束
          {
               break;
          }
          else if (msg.type == findteacher) // 查看老师名字
          {
               TESC *pIn = (TESC *)msg.buf;
               printf("请给%s打分(1-5)\n", pIn->teachername);
               scanf("%d", &pIn->score);
               msg.type = changeteacherscore;
               memcpy(msg.buf, pIn, sizeof(TESC));
               ret = send(sID, &msg, sizeof(msg), 0);
               if (ret <= 0)
               {
                    printf("发送数据失败\n");
                    return;
               }
          }
     }
}
void ShowMessage(int sID) // 查看留言
{
     MSG msg;
     msg.type = viewmessage;
     strcpy(msg.buf, LoginUserName);
     int ret = send(SID, &msg, sizeof(msg), 0);
     if (ret <= 0)
     {
          printf("发送数据失败\n");
          return;
     }
     msg.type = 100000; // 先把消息类型清空
     ret = 0;
     struct sockaddr_in serverAddr;
     socklen_t len = sizeof(serverAddr);
     while (0 < (ret = recv(sID, &msg, sizeof(msg), 0)))
     {
          if (msg.type == viewover) // 查询结束
          {
               printf("------------------------------------------------\n");
               msg.type = delemessage;
               strcpy(msg.buf, LoginUserName);
               ret = send(SID, &msg, sizeof(msg), 0);
               if (ret <= 0)
               {
                    printf("发送数据失败\n");
                    return;
               }
               break;
          }
          else if (msg.type == viewmessage) // 查看留言
          {
               PVCH *pIn = (PVCH *)msg.buf;
               printf("------------------------------------------------\n");
               printf(" %s %s %s\n", pIn->selfName, pIn->text, pIn->t);
          }
          else if (msg.type == no)
          {
               printf("没有留言\n");
               return;
          }
     }
}
void WriteHomework(int sID) // 写作业
{
     MSG msg;
     HWORK hw;
     strcpy(hw.student, LoginUserName);
     // char sub[128]; // 科目
     msg.type = viewhomework;
     printf("请输入要写的科目");
     scanf("%s", hw.subjects);
     strcpy(msg.buf, hw.subjects);
     ret = send(SID, &msg, sizeof(msg), 0);
     if (ret <= 0)
     {
          printf("发送数据失败\n");
          return;
     }
     struct sockaddr_in serverAddr;
     socklen_t len = sizeof(serverAddr);
     while (0 < (ret = recv(sID, &msg, sizeof(msg), 0)))
     {
          if (msg.type == viewover) // 查询结束
          {
               break;
          }
          else if (msg.type == viewhomework) // 查看作业
          {
               HWORK *pIn = (HWORK *)msg.buf;
               strcpy(hw.teacher, pIn->teacher);
               printf(" %s %s\n", pIn->subjects, pIn->text);
               printf("\n");
          }
          else if (msg.type == no)
          {
               printf("没有该科目作业\n");
               return;
          }
     }
     printf("请输入你的答案");
     scanf("%s", hw.text);
     msg.type = dohomework;
     memcpy(msg.buf, &hw, sizeof(HWORK));
     ret = send(SID, &msg, sizeof(msg), 0);
     if (ret <= 0)
     {
          printf("发送数据失败\n");
          return;
     }
     printf("提交成功\n");
}
void showinformation(int sID) // 显示信息
{
     MSG msg;
     msg.type = viewstudent;
     strcpy(msg.buf, LoginUserName);
     ret = send(sID, &msg, sizeof(msg), 0);
     if (ret <= 0)
     {
          printf("发送数据失败\n");
          return;
     }
     struct sockaddr_in serverAddr;
     socklen_t len = sizeof(serverAddr);
     ret = recv(sID, &msg, sizeof(msg), 0);
     SEN *pIn = (SEN *)msg.buf;
     printf(" 学号:%d 名字:%s 密码:%s 性别:%s 成绩:%d\n", pIn->id, pIn->name, pIn->pwd, pIn->sex, pIn->score);
}
void showMenu() // 学生界面主菜单
{
     bool loop = true;
     while (loop == true)
     {
          MSG msg;
          msg.type = howmessage;
          memcpy(msg.buf, &LoginUserName, sizeof(LoginUserName));
          int ret = send(SID, &msg, sizeof(msg), 0);
          if (ret <= 0)
          {
               printf("发送数据失败\n");
               return;
          }
          struct sockaddr_in serverAddr;
          socklen_t len = sizeof(serverAddr);
          ret = recv(SID, &msg, sizeof(msg), 0);
          if (ret <= 0)
          {
               printf("接收数据失败\n");
               return;
          }
          char sql[256];
          int num = atoi(msg.buf);
          sprintf(sql, "请选择你要的操作:1.私聊 2.群聊 3.查看留言%d 4.写作业 5.打评分6.查看信息 7.❌退出\n", num);
          printf("%s", sql);
          char buf[16];
          scanf("%s", buf);
          if (strcmp(buf, "1") == 0)
          {
               system("clear");
               PrivateChat(SID);
          }
          else if (strcmp(buf, "2") == 0)
          {
               system("clear");
               GroupChat(SID);
          }
          else if (strcmp(buf, "3") == 0)
          {
               system("clear");
               ShowMessage(SID);
          }
          else if (strcmp(buf, "4") == 0)
          {
               system("clear");
               WriteHomework(SID);
          }
          else if (strcmp(buf, "5") == 0)
          {
               system("clear");
               Grade(SID);
          }
          else if (strcmp(buf, "6") == 0)
          {
               system("clear");
               showinformation(SID);
          }
          else if (strcmp(buf, "7") == 0)
          {
               return;
          }
     }
}
int main(int count, char *arg[])
{
     // SEN *STU = (SEN *)malloc(sizeof(SEN));
     struct sockaddr_in sin;
     memset(&sin, 0, sizeof(sin)); // 清零
     sin.sin_family = AF_INET;     // IPV4的网络地址版本
     sin.sin_port = htons(9000);   // 把9000号端口转为网络字节序并赋值给端口参数

     u_int32_t ip = 0;
     // 把字符串ip地址转为网络字节序ip
     inet_pton(AF_INET, "192.168.91.60", &ip);
     sin.sin_addr.s_addr = ip;

     // 创建一个tcp套接字，参数1指定地址族，参数2指定协议，SOCK_STREAM代表是TCP，SOCK_DGRAM代表UDP
     int sID = socket(AF_INET, SOCK_STREAM, 0);
     SID = sID;
     while (-1 == connect(sID, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)))
     {
          perror("连接服务器中...");
          sleep(1);
     }

     char buf[128];
     while (1)
     {
          printf("请选择你要的操作:1.注册 2.登录 3.退出\n");
          scanf("%s", buf);
          if (strcmp(buf, "1") == 0) // 注册
          {
               system("clear");
               Enroll(sID);
          }
          else if (strcmp(buf, "2") == 0)
          {
               system("clear");
               Login(sID);
          }
          else if (strcmp(buf, "3") == 0)
          {
               return 0;
          }
     }

     close(sID);

     return 0;
}